﻿//  Copyright (c) 2011 Ray Liang (http://www.dotnetage.com)
//  Dual licensed under the MIT and GPL licenses:
//  http://www.opensource.org/licenses/mit-license.php
//  http://www.gnu.org/licenses/gpl.html

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.IO;
using System.Reflection;
using System.Web.Mvc;
using DNA.Mvc.Controllers;

namespace DNA.Mvc.UI
{
    public static class Dashboard
    {
        public static IEnumerable<DashboardGroup> SystemGroups
        {
            get
            {
                return GetItemGroups<SiteControlPanelAttribute>(WebSiteContext.Current);
            }
        }

        public static IEnumerable<DashboardGroup> PersonalGroups
        {
            get
            {
                return GetItemGroups<MyControlPanelAttribute>(WebSiteContext.Current);
            }
        }

        //public static IEnumerable<DashboardGroup> Groups
        //{
        //    get
        //    {
        //        var context = WebSiteContext.Current;
        //        if (context.Web.IsRoot)
        //            return GetItemGroups<SiteControlPanelAttribute>(context);
        //        else
        //            return GetItemGroups<MyControlPanelAttribute>(context);
        //    }
        //}

        private static IEnumerable<DashboardGroup> GetItemGroups<T>(WebSiteContext context)
            where T : ControlPanelAttribute
        {
            var groups = new List<DashboardGroup>();
            var items = new List<DashboardItem>();

            string[] files = Directory.GetFiles(HttpContext.Current.Server.MapPath("~/bin"), "*.dll");
            var url = UrlUtility.CreateUrlHelper();

            foreach (string file in files)
            {
                try
                {
                    Assembly assembly = Assembly.LoadFrom(file);
                    AssemblyName asmname = assembly.GetName();
                    Type[] types = assembly.GetTypes();

                    var controllers = from c in types
                                      where c.BaseType == typeof(Controller)
                                      select c;

                    foreach (Type controller in controllers)
                    {
                        var methods = controller.GetMethods(BindingFlags.Public | BindingFlags.Instance);
                        var actions = from MethodInfo method in methods
                                      where (method.GetCustomAttributes(typeof(T), true).Length > 0)
                                      select method;

                        foreach (MethodInfo action in actions)
                        {
                            T attr = (T)Attribute.GetCustomAttribute(action, typeof(T));
                            string text = attr.Text;
                            var securityAttr = Attribute.GetCustomAttribute(action, typeof(SecurityActionAttribute));
                            var webType = (WebTypes)context.Web.Type;

                            if (attr.GetType().Equals(typeof(MyControlPanelAttribute)) )
                            {
                                var attrType = attr as MyControlPanelAttribute;
                                if (!context.EnablePersonalWeb && attrType.ShowInPersonalSiteOnly)
                                    continue;
                            }


                            if (attr.GetType().Equals(typeof(SiteControlPanelAttribute)))
                            {
                                var teamAttr = attr as SiteControlPanelAttribute;
                                if (teamAttr.ShowInTopSiteOnly && !context.Web.IsRoot)
                                    continue;
                            }

                            //if (securityAttr != null)
                            //{
                            //    if (context.EnablePersonalWeb)
                            //    {
                            //        //Permission check
                            //        if ((!context.IsAuthorized(controller, action.Name)) && (!HttpContext.Current.User.IsWebOwner()))
                            //            continue;
                            //    }
                            //    else
                            //    {
                            //        if (context.Web.IsRoot)
                            //        {
                            //            if ((!context.IsAuthorized(controller, action.Name)) && (!HttpContext.Current.User.IsWebOwner()))
                            //                continue;
                            //        }
                            //        else
                            //        {
                            //            if (!context.IsAuthorized(controller, action.Name))
                            //                continue;
                            //        }
                            //    }
                            //}

                            var httpPostAttr = Attribute.GetCustomAttribute(action, typeof(HttpPostAttribute));
                            if (httpPostAttr != null) 
                                continue;

                            if (!string.IsNullOrEmpty(attr.ResKey))
                            {
                                if (!string.IsNullOrEmpty(attr.ResBaseName))
                                    text = GlobalizationExtensions.Global(null, attr.ResBaseName, attr.ResKey);
                                else
                                    text = GlobalizationExtensions.Global(null, attr.ResKey);
                            }

                            string _controller = controller.Name.Replace("Controller", "");
                            var curGroup = groups.FirstOrDefault(g => g.Name.Equals(attr.Group, StringComparison.OrdinalIgnoreCase));

                            if (curGroup == null)
                            {
                                curGroup = new DashboardGroup() { Name = attr.Group };
                                groups.Add(curGroup);
                            }

                            if (!string.IsNullOrEmpty(attr.GroupResKey) && !string.IsNullOrEmpty(attr.ResBaseName) && string.IsNullOrEmpty(curGroup.Title))
                                curGroup.Title = HttpContext.GetGlobalResourceObject(attr.ResBaseName, attr.GroupResKey) as string;

                            var _item = new DashboardItem()
                            {
                                Order = attr.Sequence,
                                Title = text,
                                NavigationUrl = url.Action(action.Name, _controller, new { Area = GetArea(controller), website = context.Web.Name })
                            };

                            if (!context.EnablePersonalWeb && attr.GetType().Equals(typeof(MyControlPanelAttribute)))
                            {
                                _item.NavigationUrl = url.Action(action.Name, _controller, new { Area = GetArea(controller) });
                            }

                            curGroup.Items.Add(_item);
                        }
                    }
                }
                catch (Exception e)
                {
                    continue;
                }
            }
            return groups.OrderBy(g => g.Name).ToList();
        }

        private static string GetArea(Type ctrlType)
        {
            var types = ctrlType.Assembly.GetTypes();
            var areaRegistrationType= types.FirstOrDefault(t=>t.BaseType!=null && t.BaseType.Equals(typeof(AreaRegistration)));
            if (areaRegistrationType == null)
                return "";
            else
            { 
                var areaInstance=(AreaRegistration)Activator.CreateInstance(areaRegistrationType);
                return areaInstance.AreaName;
            }
        }
    }

}